/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-8-30
 * Author: Seapeak.Xu
 */


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>

#include "fost_propreader.h"
#include "fost_string.h"
#include "fost_mem.h"
#include "fost_typedef.h"
#include "fost_logger.h"

static int read_propfile(FILE *file, value_setter_callback func);

int prop_init(char *path, value_setter_callback func)
{
	int result = 0;
	if (NULL == path || 0 == strlen(path))
	{
		result = 0 == errno ? EINVAL : errno;
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__, __LINE__,
				__FUNCTION__, result,strerror(result));
		return result;
	}

	struct stat buf;
	if (-1 == stat(path, &buf))
	{
		result = 0 == errno ? EACCES : errno;
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__, __LINE__,
				__FUNCTION__, result,strerror(result));
		return result;
	}

	if (!S_ISREG(buf.st_mode))
	{
		result = 0 == errno ? ENOENT : errno;
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__, __LINE__,
				__FUNCTION__, result,strerror(result));
		return result;
	}

	if (-1 == access(path, R_OK))
	{
		result = 0 == errno ? EACCES : errno;
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__, __LINE__,
				__FUNCTION__, result,strerror(result));
		return result;
	}

	FILE *file = fopen(path, "r");
	if (NULL == file)
	{
		result = 0 == errno ? EIO : errno;
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.", __FILE__, __LINE__,
				__FUNCTION__, result,strerror(result));
		return result;
	}

	if (0 != (result = read_propfile(file, func)))
	{
		log_error("File:%s,Line:%d,Function:%s.Errno:%d,Info:%s.",
				__FILE__,__LINE__,__FUNCTION__,result,strerror(result));
		return result;
	}

	return result;
}

static int read_propfile(FILE *file, value_setter_callback func)
{
	char *line;
	char *key;
	char *value;
	int result = 0;
	do
	{
		line = fost_callocs(LINE_LEN);
		key = fost_callocs(CONFKEY_LEN);
		value = fost_callocs(CONFVALUE_LEN);
		if (NULL == line || NULL == key || NULL == value)
		{
			result = 0 == errno ? EINVAL : errno;
			log_error("File:%s,Line:%d,Function:%s.malloc memory is error.errno:%d,info:%s.",
					__FILE__,__LINE__,__FUNCTION__,result,strerror(result));
			break;
		}
		char *pequ;
		int key_length;
		while (NULL != fgets(line, LINE_LEN, file))
		{
			if (NULL == line || 0 == strlen(line) || 0 == strlen(trim(line)))
			{
				continue;
			}

			if ('#' == *line)
			{
				continue;
			}

			pequ = strchr(line, '=');
			key_length = pequ - line;
			if (key_length == strlen(line))
			{
				result = EBFONT;
				log_error("File:%s,Line:%d,Function:%s.the configure file is just key!Error:%d,Info:%s.",
						__FILE__,__LINE__,__FUNCTION__,result,strerror(result));
				break;
			}
			memcpy(key, line, key_length);
			memcpy(value, line + key_length + 1, strlen(line) - key_length - 1);
			trim(key);
			trim(value);

			if (0 != (result = func(key,value)))
			{
				log_error("File:%s,Line:%d,Function:%s.set value is error.Error:%d,Info:%s.",
						__FILE__,__LINE__,__FUNCTION__,result,strerror(result));
				break;
			}

			//clean the old memory
			pequ = NULL;
			key_length = 0;
			memset(line, 0, LINE_LEN);
			memset(key, 0, CONFKEY_LEN);
			memset(value, 0, CONFVALUE_LEN);
		}
	} while (false);

	FOST_FREE(line);
	FOST_FREE(key);
	FOST_FREE(value);
	return 0;
}

int set_int(int *result, const char *value, const int initial)
{
	if (NULL == value || 0 == strlen(value))
	{
		*result = initial;
		return 0;
	}
	*result = atoi(value);
	return 0;
}

int set_string(char *result, const char *value, const char *initial)
{
	if (NULL == value || 0 == strlen(value))
	{
		memcpy(result, initial, strlen(initial));
		return 0;
	}

	memcpy(result, value, strlen(value));
	return 0;
}

int set_bool(bool *result, const char *value, const bool initial)
{
	if (NULL == value || 0 == strlen(value))
	{
		*result = initial;
		return 0;
	}
	if (0 == strcasecmp(value, "false"))
	{
		*result = false;
	}
	else
	{
		*result = true;
	}
	return 0;
}

int set_double(double *result,const char *value,const double initial)
{
	if(NULL == value || 0 == strlen(value))
	{
		*result = initial;
		return 0;
	}
	*result = atof(value);
	return 0;
}

int set_long(long *result,const char *value,const long initial)
{
	if (NULL == value || 0 == strlen(value))
	{
		*result = initial;
		return 0;
	}
	*result = atol(value);
	return 0;
}
